home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / uudecode.i < prev    next >
Text File  |  1997-10-26  |  8KB  |  302 lines

  1. IMPLEMENTATION MODULE UUDecode;
  2.  
  3. FROM SYSTEM IMPORT CAST, BYTE, ADR, CADR, CALLSYS, ASSEMBLER;
  4.  
  5. IMPORT FileNames, Strings;
  6.  
  7. (* CAT-Module *)
  8. IMPORT CatTypes, CatFiles, CatGlobal;
  9.  
  10. FROM EditTypes IMPORT CAT;
  11.  
  12. (*$? CAT:
  13. FROM Protokoll IMPORT SendPathUpdate;
  14. *)
  15.  
  16. (*$? NOT CAT:
  17. FROM FredProtokoll IMPORT SendPathUpdate;
  18. *)
  19.  
  20. (* Magic-Module *)
  21. IMPORT mtTextfiles;
  22.  
  23. FROM Void IMPORT v;
  24.  
  25. CONST   textFiles = TRUE;
  26.  
  27. TYPE decodeErrType = (noErr, lineToShort, illCharInLine);
  28.  
  29. CONST offset = 32;
  30.  
  31. VAR decodePath: CatTypes.String255;
  32.     decodeFile: INTEGER;
  33.     decodeErr : decodeErrType;
  34.     textFile  : mtTextfiles.TEXTFILE;
  35.     lastLine  : ARRAY [0..79] OF CHAR;
  36.     checkLastLine : BOOLEAN;
  37.  
  38. PROCEDURE BeginDecode();
  39. (* Initialisiert die Dekodierung 
  40.  *)
  41. BEGIN
  42.   (* DecodePath setzen *)
  43.   (* Strings.Assign (".\", decodePath, v.bool); *)
  44.   (* DecodeFile zurcksetzen *)
  45.   decodeFile := -1;  
  46.   decodeErr := noErr;
  47.   checkLastLine := FALSE;
  48. END BeginDecode;
  49.  
  50. PROCEDURE iDecodeLine(REF line: ARRAY OF CHAR; validCheck: BOOLEAN): BOOLEAN;
  51. (* Dekodiert eine Zeile 
  52.  *)
  53.  VAR lineIndex, byteNum, count, i: INTEGER;
  54.      chars: ARRAY [0..3] OF BYTE;
  55.      hunk: ARRAY [0..2] OF BYTE;
  56.      fname  : CatTypes.String255;
  57.      len    : INTEGER;
  58.      calcLen: INTEGER;
  59.      processLine : BOOLEAN;
  60.      tmp    : ARRAY [0..7] OF CHAR;
  61.  
  62.   PROCEDURE nextch (): CHAR;
  63.  
  64.     BEGIN
  65.       INC (lineIndex);
  66.       IF lineIndex > len
  67.       THEN
  68.         RETURN ' '; (* abort('Line too short.'); *)
  69.       END;
  70.       IF NOT (line[lineIndex] IN CatTypes.charSet{0C,' '..'`'})
  71.       THEN 
  72.         decodeErr := illCharInLine;
  73.         RETURN 0C; (* abort('Illegal character in line.'); *)
  74.       END;
  75.       IF (line[lineIndex] = '`') OR (line[lineIndex] = 0C)
  76.       THEN 
  77.         RETURN ' '
  78.       ELSE
  79.         RETURN line[lineIndex]
  80.       END;
  81.     END nextch;
  82.  
  83.   PROCEDURE DecodeByte ();
  84.  
  85.     PROCEDURE GetNextHunk ();
  86.  
  87.       VAR i: INTEGER;
  88.  
  89.       BEGIN 
  90.         (*$R-*)
  91.         FOR i := 0 TO 3 DO 
  92.           chars[i] := SHORT(ORD(nextch()) - offset); 
  93.         END;
  94.         ASSEMBLER
  95.           MOVE.L    (A6),A0     ; A0 ist Zeiger auf Variablen von DecodeByte
  96.           MOVE.L    (A0),A0     ; A0 zeigt auf Variablen von DecodeLine
  97.           LEA       chars(A0),A1    ; A1 ist Basisadresse von chars
  98.           LEA       hunk(A0),A2    ; A2 ist Basisadresse von hunk 
  99.           MOVE.B    0(A1),D0
  100.           LSL.B     #2,D0       ; chars[0] shl 2
  101.           MOVE.B    1(A1),D1
  102.           MOVE.B    D1,D2       ; chars[1] in D1,D2
  103.           LSR.B     #4,D1       ; chars[1] shr 4
  104.           ADD.B     D1,D0
  105.           MOVE.B    D0,(A2)+
  106.           LSL.B     #4,D2       ; chars[1] shl 4
  107.           MOVE.B    2(A1),D0    
  108.           MOVE.B    D0,D1       ; chars[2] in D0,D1
  109.           LSR.B     #2,D0       ; chars[2] shr 2
  110.           ADD.B     D2,D0
  111.           MOVE.B    D0,(A2)+
  112.           LSL.B     #6,D1
  113.           ADD.B     3(A1),D1
  114.           MOVE.B    D1,(A2)
  115.         END;
  116.         (*
  117.         hunk[0] := SHORT(ORD(chars[0]) * 4 + ORD(chars[1]) DIV 16);
  118.         hunk[1] := SHORT(ORD(chars[1]) * 16 + ORD(chars[2]) DIV 4);
  119.         hunk[2] := SHORT(ORD(chars[2]) * 64 + ORD(chars[3]));
  120.         *)
  121.         (*$R=*)
  122.         (*$R- wegen Compiler-Bug*)
  123.         (*
  124.         hunk[0] := (chars[0] shl 2) + (chars[1] shr 4);
  125.         hunk[1] := (chars[1] shl 4) + (chars[2] shr 2);
  126.         hunk[2] := (chars[2] shl 6) + chars[3];
  127.         *)
  128.         byteNum := 0;
  129.       END GetNextHunk;
  130.  
  131.   BEGIN 
  132.     IF byteNum = 3 THEN 
  133.       GetNextHunk ();
  134.       IF decodeErr # noErr
  135.       THEN
  136.         RETURN
  137.       END;
  138.     END;
  139.     (*$? NOT textFiles:
  140.     CatFiles.WriteFile (CHAR(hunk[byteNum]), decodeFile);
  141.     *)
  142.     (*$? textFiles:
  143.     mtTextfiles.WriteChar (textFile, CHAR(hunk[byteNum]));
  144.     *)
  145.     INC (byteNum);
  146.   END DecodeByte;
  147.  
  148. BEGIN 
  149.   (* Erstmal feststellen, was fr eine Zeile es ist *)
  150.   len := INTEGER (LENGTH(line));
  151.   IF Strings.Pos ("begin", line, 0) = 0
  152.   THEN
  153.     (* Anfang eines Files *)
  154.     (* Haben wir noch eines offen? Das mssen wir dann zumachen! *)
  155.     IF decodeFile > 0
  156.     THEN
  157.       (* CheckLastLine mssen wir hier nicht machen,
  158.        * vor einem begin kann keine gltige Zeile eines
  159.        * anderen UUs kommen
  160.        *) 
  161.       checkLastLine := FALSE;
  162.       (*$? NOT textFiles:
  163.       CatFiles.CloseFile (decodeFile);
  164.       *)
  165.       (*$? textFiles:
  166.       mtTextfiles.CloseTextfile (textFile);
  167.       *)
  168.       decodeFile := -1;
  169.       SendPathUpdate (decodePath);
  170.     END;
  171.     (* Anfang eines Files *)
  172.     (* Dateinamen Suchen *)
  173.     i := Strings.Pos (" ", line, 7);
  174.     IF i < 0 THEN RETURN FALSE END;
  175.     Strings.Copy (line, i+1, len - i - 1, fname, v.bool);
  176.     (* Datei zur Auswahl anbieten *)
  177.     IF CatGlobal.FselGet(decodePath, fname, "*.*", "Decodieren nach", FALSE) THEN
  178.       (* Datei erzeugen *)
  179.       (*$? textFiles:
  180.       Strings.Insert (decodePath, 0, fname, v.bool);
  181.       IF mtTextfiles.OpenTextfile (fname, mtTextfiles.WRITE, 32000, textFile)
  182.       OR mtTextfiles.OpenTextfile (fname, mtTextfiles.WRITE, 512, textFile)
  183.       THEN
  184.         decodeFile := 1;
  185.       END;
  186.       *)
  187.       (*$? NOT textFiles:
  188.       decodeFile := CatFiles.CreateFile (decodePath, fname);
  189.       IF decodeFile < 0
  190.       THEN
  191.         CatFiles.ErrorAlert (decodeFile);
  192.         RETURN FALSE;
  193.       END;
  194.       *)
  195.     END;
  196.   ELSIF Strings.Pos ("end", line, 0) = 0
  197.   THEN
  198.     (* Ende eines Files *)
  199.     IF decodeFile > 0
  200.     THEN
  201.       IF checkLastLine
  202.       THEN
  203.         checkLastLine := FALSE;
  204.         IF ~iDecodeLine (lastLine, FALSE)
  205.         THEN
  206.           RETURN FALSE
  207.         END;
  208.       END;
  209.       (*$? NOT textFiles:
  210.       CatFiles.CloseFile (decodeFile);
  211.       *)
  212.       (*$? textFiles:
  213.       mtTextfiles.CloseTextfile (textFile);
  214.       *)
  215.       decodeFile := -1;
  216.     END;
  217.   ELSE
  218.     IF decodeFile > 0
  219.     THEN
  220.       (* M”glicherweise eine UU-Zeile *)
  221.       lineIndex := -1;
  222.       byteNum := 3;
  223.       count := INTEGER(ORD(nextch()) - offset);
  224.       calcLen := (count DIV 3) * 4;
  225.       IF validCheck & (calcLen = len)
  226.       THEN
  227.         (* Ein Byte fehlt am Ende, L„nge auffllen, die MAUS hat
  228.          * ein Leerzeichen abgebissen
  229.          *)
  230.         INC (len);
  231.       END;
  232.       processLine := ~validCheck OR (calcLen = len - 1) OR (calcLen = len - 2);
  233.       IF len = 1
  234.       THEN
  235.         processLine := FALSE;
  236.       ELSIF ~processLine
  237.       THEN
  238.         (* Zeile noch genauer untersuchen *)
  239.         Strings.Copy (line, 0, 5, tmp, v.bool);
  240.         IF ~Strings.StrEqual (tmp, "-----")      (* definitiv ein Trenner, wenn identisch *)
  241.         THEN
  242.           (* also kein Trenner, mal optimistisch sein *)
  243.           processLine := (len <= 64) & (* Wir nehmen in dem Fall mal an, daž es eine UU-Zeile ist *)
  244.                          (line[0] >= ' ') & (line[0] <= 'R');
  245.         END;
  246.       END;
  247.       IF processLine
  248.       THEN
  249.         IF checkLastLine
  250.         THEN
  251.           checkLastLine := FALSE;
  252.           IF ~iDecodeLine (lastLine, FALSE)
  253.           THEN
  254.             RETURN FALSE
  255.           END;
  256.         END;
  257.         (* wohl UU-Zeile, verarbeiten *)
  258.         FOR i := 0 TO count-1 DO 
  259.           DecodeByte ();
  260.           IF decodeErr # noErr
  261.           THEN
  262.             RETURN FALSE
  263.           END;
  264.         END;
  265.       ELSIF ((count DIV 3) * 4 > len) & (len < 80) & (len > 1)
  266.       THEN
  267.         (* m”glicherweise Leerzeichen abgeschnitten *)
  268.         Strings.Assign (line, lastLine, v.bool);
  269.         checkLastLine := TRUE;
  270.       END;
  271.     END;
  272.   END;
  273.   RETURN TRUE;
  274. END iDecodeLine;
  275.  
  276. PROCEDURE DecodeLine(REF line: ARRAY OF CHAR): BOOLEAN;
  277. BEGIN
  278.   RETURN iDecodeLine (line, TRUE);
  279. END DecodeLine;
  280.  
  281. PROCEDURE EndDecode ();
  282. (* Beendet die Dekodierung, schliežt ggf. offene Dateien
  283.  *)
  284. BEGIN
  285.   (* Ende eines Files *)
  286.   IF decodeFile > 0
  287.   THEN
  288.     (*$? textFiles:
  289.     mtTextfiles.CloseTextfile (textFile);
  290.     *)
  291.     (*$? NOT textFiles:
  292.     CatFiles.CloseFile (decodeFile);
  293.     *)
  294.     decodeFile := -1;
  295.     SendPathUpdate (decodePath);
  296.   END;
  297. END EndDecode;
  298.  
  299. BEGIN
  300.   decodePath := "";
  301. END UUDecode.
  302.